#ifdef _WIN32
#include <Windows.h>
#include "Atomic.h"

using namespace Stray;
using namespace Stray::Core;

Atomic::Atomic(Int32 value)
	:value_(value)
{
#ifdef _DEBUG 
#pragma warning(disable:4101) 
	int check[sizeof(Int32) == sizeof(LONG)];
#endif
}

Atomic::~Atomic()
{
}

Int32 Atomic::get() const
{
	return InterlockedExchangeAdd(
		reinterpret_cast<volatile LONG*>(&const_cast<volatile Int32&>(value_)),
		0);
}

void Atomic::set(Int32 value)
{
	InterlockedExchange(reinterpret_cast<volatile LONG*>(&value_), value);
}

Int32 Atomic::add(Int32 value)
{
	return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&value_), value);
}

Int32 Atomic::increment()
{
	return InterlockedIncrement(reinterpret_cast<volatile LONG*>(&value_));
}

Int32 Atomic::decrement()
{
	return InterlockedDecrement(reinterpret_cast<volatile LONG*>(&value_));	
}

Atomic& Atomic::operator=(const Atomic& rhs)
{
	if(this != &rhs)
	{
		set(rhs.get());
	}

	return *this;
}

Atomic& Atomic::operator=(Int32 rhs)
{
	set(rhs);
	return *this;
}

Atomic& Atomic::operator++()
{
	increment();
	return *this;
}

Atomic& Atomic::operator--()
{
	decrement();
	return *this;
}

bool operator==(const Atomic& lhs, const Atomic& rhs)
{
	return lhs.get() == rhs.get();
}

bool operator!=(const Atomic& lhs, const Atomic& rhs)
{
	return lhs.get() != rhs.get();
}

bool operator<=(const Atomic& lhs, const Atomic& rhs)
{
	return lhs.get() <= rhs.get();
}

bool operator<(const Atomic& lhs, const Atomic& rhs)
{
	return lhs.get() < rhs.get();
}

bool operator>=(const Atomic& lhs, const Atomic& rhs)
{
	return lhs.get() >= rhs.get();
}

bool operator>(const Atomic& lhs, const Atomic& rhs)
{
	return lhs.get() > rhs.get();
}

#endif